﻿using System;
using System.Data.Services.Client;
using System.Globalization;
using System.Windows;
using BazookaBird.Sl.Data.Helpers;
using BazookaBird.Sl.Data.Model;
using Caliburn.Micro;

namespace Bazookabird.Sl {
    using System.ComponentModel.Composition;

    [Export(typeof(IShell))]
    public class ShellViewModel : PropertyChangedBase, IShell
    {
        private const string Filename = "bazookabird.isolated";


        protected bool IsLoggingIn { get; set; }

        public ShellViewModel()
        {
            Credentials = IsolatedStorageHelper.ReadCredentials(Filename);
        }

        private TfsCredentials _credentials;
        public TfsCredentials Credentials
        {
            get { return _credentials; }
            set
            {
                _credentials = value;
                NotifyOfPropertyChange(() => Credentials);
            }
        }


        public void Connect()
        {
            IsolatedStorageHelper.SaveCredentials(Credentials, Filename);
            var context = TfsConnectionHelper.CreateTfsDataServiceContext(Credentials);
            Login(context, r =>
            {
                if (!r.IsAuthenticated)
                {
                    MessageBox.Show(r.Description, "Authentication Error", MessageBoxButton.OK);
                }
                else
                {
                    
                }
            });
        }

        public bool CanConnect { get { return true; } }

        public void Login(TFSData context, Action<LoginResult> callback)
        {
            string errorMessage;
            if (!Validate(out errorMessage))
            {
                callback.Invoke(new LoginResult { IsAuthenticated = false, Description = errorMessage });
                return;
            }

            this.IsLoggingIn = true;
            var requestUri = new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/Projects('{1}')", Credentials.CollectionPath, Credentials.ProjectName), UriKind.Absolute);

            context.BeginExecute<Project>(
                requestUri,
                r =>
                {
                    try
                    {
                        var result = context.EndExecute<Project>(r) as QueryOperationResponse<Project>;
                        if (result != null)
                        {
                            // Save the valid credentials in the Isolated Storage
                            IsolatedStorageHelper.ClearCredentials(Filename);
                            IsolatedStorageHelper.SaveCredentials(Credentials, Filename);

                            this.DispatchResult(callback, new LoginResult { IsAuthenticated = true, Description = string.Empty });
                        }
                    }
                    catch (Exception ex)
                    {
                        Exception dataServiceException;
                        var result = new LoginResult { IsAuthenticated = false, Description = ex.Message };

                        if (DataServiceExceptionUtil.TryParse(ex, out dataServiceException))
                        {
                            result.Description = dataServiceException.Message;
                        }
                        else if (ex.InnerException != null)
                        {
                            result.Description = ex.InnerException.Message;
                        }

                        DispatchResult(callback, result);
                    }
                },
                null);
        }

        private void DispatchResult(Action<LoginResult> callback, LoginResult result)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
                                                          {
                                                              IsLoggingIn = false;
                                                              callback.Invoke(result);
                                                          });
        }

        private bool Validate(out string errorMessage)
        {
            errorMessage = string.Empty;

            Uri tfsServerUri;
            if (!Uri.TryCreate(Credentials.CollectionPath, UriKind.Absolute, out tfsServerUri))
            {
                errorMessage = "The OData service for Team Foundation Server endpoint URL is not valid.";
                return false;
            }

            if ((tfsServerUri.Scheme != Uri.UriSchemeHttp) && (tfsServerUri.Scheme != Uri.UriSchemeHttps))
            {
                errorMessage = "The Uri scheme used is not supported. Please use HTTP or HTTPS schemes.";
                return false;
            }

            return true;
        }
    }
}
